package br.ucb.cm.board.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import br.ucb.cm.board.bean.Location;
import br.ucb.cm.board.bean.Move;
import br.ucb.cm.board.bean.Piece;
import br.ucb.cm.config.GameInstance;
import br.ucb.cm.config.bean.Movimentation;
import br.ucb.cm.config.bean.PieceConfig;
import br.ucb.cm.main.common.GeneralConstants.PlayerEnum;

public class MovementUtil {
	public static final int MOVE = 0;
	public static final int ATTACK = 1;
	public static final int UP = 1;
	public static final int DOWN = -1;
	public static final int LEFT = -1;
	public static final int RIGHT = 1;
	public static final int IDLE = 0;
	
	private static int boardHeight;
	private static int boardWidth;
	private PlayerEnum player;
	private int moveType;

	public MovementUtil(PlayerEnum player, int moveType) {
		boardHeight = GameInstance.getInstance().getConfig().getBoard().getHeight();
		boardWidth = GameInstance.getInstance().getConfig().getBoard().getWidth();
		this.moveType = moveType;
		this.player = player;
	}

	public List<Move> verticalMoves(Piece piece, Map<Location, PieceConfig> pieceMap) {
		List<Move> moveList = new ArrayList<Move>();
		Movimentation movimentation = (moveType == MOVE) ? piece.getConfig().getMoves() : piece.getConfig().getAttack();

		moveList.addAll(getMoves(piece, pieceMap, movimentation.canUp(), movimentation.canMaxVertical(), UP, IDLE));
		moveList.addAll(getMoves(piece, pieceMap, movimentation.canDown(), movimentation.canMaxVertical(), DOWN, IDLE));
		
		return moveList;
	}
	
	public List<Move> horizontalMoves(Piece piece, Map<Location, PieceConfig> pieceMap) {
		List<Move> moveList = new ArrayList<Move>();
		Movimentation movimentation = (moveType == MOVE) ? piece.getConfig().getMoves() : piece.getConfig().getAttack();

		moveList.addAll(getMoves(piece, pieceMap, movimentation.canLeft(), movimentation.canMaxHorizontal(), IDLE, LEFT));
		moveList.addAll(getMoves(piece, pieceMap, movimentation.canRight(), movimentation.canMaxHorizontal(), IDLE, RIGHT));
		
		return moveList;
	}
	
	public List<Move> diagonalMoves(Piece piece, Map<Location, PieceConfig> pieceMap) {
		List<Move> moveList = new ArrayList<Move>();
		Movimentation movimentation = (moveType == MOVE) ? piece.getConfig().getMoves() : piece.getConfig().getAttack();

		moveList.addAll(getMoves(piece, pieceMap, movimentation.canUpLeft(),    movimentation.canMaxDiagonal(), UP,   LEFT));
		moveList.addAll(getMoves(piece, pieceMap, movimentation.canUpRight(),   movimentation.canMaxDiagonal(), UP,   RIGHT));
		moveList.addAll(getMoves(piece, pieceMap, movimentation.canDownLeft(),  movimentation.canMaxDiagonal(), DOWN, LEFT));
		moveList.addAll(getMoves(piece, pieceMap, movimentation.canDownRight(), movimentation.canMaxDiagonal(), DOWN, RIGHT));
		
		return moveList;
	}

	public List<Move> getMoves(Piece piece, Map<Location, PieceConfig> pieceMap, boolean canDo, boolean canMax, int verticalFactor, int horizontalFactor) {
		List<Move> moveList = new ArrayList<Move>();
		int x = piece.getLocation().getX();
		int y = piece.getLocation().getY();

		if (canDo) {
			int xPos = x;
			int yPos = y;
			boolean foundPiece = true;
			boolean isValid = true;

			do {
				xPos = (player.equals(PlayerEnum.PLAYER_ONE)) ? xPos + horizontalFactor : xPos - horizontalFactor;
				yPos = (player.equals(PlayerEnum.PLAYER_ONE)) ? yPos - verticalFactor : yPos + verticalFactor;
				Location location = new Location(xPos, yPos);

				isValid = yPos < boardHeight && yPos >= 0 && xPos < boardWidth && xPos >= 0;
				foundPiece = pieceMap.containsKey(location);

				if (!foundPiece && isValid && moveType == MOVE)
					moveList.add(new Move(piece.getConfig(), piece.getLocation(), location));
				else if (foundPiece	&& moveType == ATTACK && BoardUtil.isEnemy(pieceMap.get(location), piece.getOwner()))
					moveList.add(new Move(piece.getConfig(), piece.getLocation(), location));
			} while (!foundPiece && isValid && canMax);
		}

		return moveList;
	}

}